package com.by.zhdoctor.web.rest;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.by.zhdoctor.huanxin.api.FileApi;
import com.by.zhdoctor.huanxin.api.IMUserApi;
import com.by.zhdoctor.huanxin.api.SendMsgApi;
import com.by.zhdoctor.huanxin.model.AudioMsgContent;
import com.by.zhdoctor.huanxin.model.ImageMsgContent;
import com.by.zhdoctor.repository.UserRepository;
import com.by.zhdoctor.security.SecurityUtils;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.client.model.Msg;
import io.swagger.client.model.MsgContent;
import io.swagger.client.model.NewPassword;
import io.swagger.client.model.RegisterUsers;
import io.swagger.client.model.User;
import io.swagger.client.model.UserName;
import io.swagger.client.model.UserNames;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;

/**
 * 对外暴露IM接口
 * Created by succy on 17-9-3.
 */
@RestController
@RequestMapping("/api/im")
public class IMResource {
    private static final Logger log = LoggerFactory.getLogger(IMResource.class);
    @Autowired
    private UserRepository userRepository;

    @Autowired
    private IMUserApi userApi;

    @Autowired
    private SendMsgApi sendMsgApi;

    @Autowired
    private FileApi fileApi;

    // ------IM用户--------
    @ApiOperation(value = "创建一个IM用户账号",
        notes = "注册成功后，使用注册成功的手机号为注册成功的用户创建一个IM用户账号，该账号可用于与其他IM用户进行通讯")
    @ApiImplicitParam(value = "用户用于登录的手机号", name = "login", required = true, dataType = "String")
    @ApiResponses({
        @ApiResponse(code = 400, message = "用户名为空或该用户已存在"),
        @ApiResponse(code = 404, message = "找不到对应{login}的已注册用户"),
        @ApiResponse(code = 201, message = "成功创建一个IM用户账号")
    })
    @PostMapping("/users/create")
    public ResponseEntity<?> createIMUser(@RequestBody String login) {
        if (StringUtils.isBlank(login)) {
            log.error("[创建IM用户] 用户名为空");
            return ResponseEntity.badRequest().body("用户名为空");
        }
        return userRepository.findOneByLogin(login).map(
            user -> {
                String username = user.getLogin();
                String password = user.getPassword();
                RegisterUsers users = new RegisterUsers();
                users.add(new User().username(username).password(password));
                io.swagger.client.ApiResponse<?> result = userApi.createIMUserSingle(users);
                Object data = result.getData();
                if (result.getStatusCode() == 400 && data == null) {
                    log.error("[创建IM用户] 该IM用户已存在");
                    return ResponseEntity.badRequest().body("该IM用户已存在");
                }
                return new ResponseEntity<>(data, HttpStatus.CREATED);
            }
        ).orElseGet(() -> new ResponseEntity<>("该账号用户不存在", HttpStatus.NOT_FOUND));
    }

    @ApiOperation(value = "重置IM用户的密码",
        notes = "重置IM用户的密码，一般情况下，在重置正和用户密码之后调用该接口重置对应环信用户的密码")
    @ApiImplicitParam(value = "新密码", name = "newPassword", required = true, paramType = "body", dataType = "String")
    @ApiResponses({
        @ApiResponse(code = 400, message = "重置密码失败"),
        @ApiResponse(code = 404, message = "该IM用户不存在"),
        @ApiResponse(code = 200, message = "重置密码成功")
    })
    @PutMapping("/users/reset")
    public ResponseEntity<?> resetUserPassword(@RequestParam String newPassword) {
        if (StringUtils.isBlank(newPassword)) {
            log.error("[重置密码] 新密码为空");
            return ResponseEntity.badRequest().body("新密码为空");
        }

        String username = SecurityUtils.getCurrentUserLogin();
        io.swagger.client.ApiResponse<?> result = userApi.resetUserPassword(username, new NewPassword().newpassword(newPassword));
        if (result.getStatusCode() == 404) {
            log.error("[重置密码] 该IM用户不存在;用户名:{}", username);
            return new ResponseEntity<Object>("该IM用户不存在", HttpStatus.NOT_FOUND);
        }
        if (result.getStatusCode() == 400) {
            log.error("[重置密码] 重置密码失败");
            return new ResponseEntity<Object>("重置密码失败", HttpStatus.BAD_REQUEST);
        }
        return ResponseEntity.ok().body(result.getData());
    }

    @ApiOperation(value = "给IM用户添加好友", notes = "给IM用户添加好友")
    @ApiImplicitParam(value = "好友的账号", name = "friendName", required = true, paramType = "query", dataType = "String")
    @ApiResponses({
        @ApiResponse(code = 404, message = "此IM用户或被添加的好友不存在"),
        @ApiResponse(code = 200, message = "添加好友成功")
    })
    @PostMapping("/users/friends")
    public ResponseEntity<?> addFriend(@RequestParam String friendName) {
        if (StringUtils.isBlank(friendName)) {
            log.error("[添加好友] 好友用户名为空");
            return ResponseEntity.badRequest().body("好友用户名为空");
        }
        String username = SecurityUtils.getCurrentUserLogin();
        io.swagger.client.ApiResponse<?> result = userApi.addFriend(username, friendName);
        if (result.getStatusCode() == 404) {
            log.error("[添加好友] 此IM用户或被添加的好友不存在");
            return new ResponseEntity<Object>("此IM用户或被添加的好友不存在", HttpStatus.NOT_FOUND);
        }
        return ResponseEntity.ok().body(result.getData());
    }

    @ApiOperation(value = "解除IM用户的好友关系", notes = "解除IM用户的好友关系")
    @ApiImplicitParam(value = "好友的账号", name = "friendName", required = true, paramType = "query", dataType = "String")
    @ApiResponses({
        @ApiResponse(code = 404, message = "此IM用户或被解除的好友不存在"),
        @ApiResponse(code = 200, message = "解除关系成功")
    })
    @DeleteMapping("/users/friends")
    public ResponseEntity<?> removeFriend(@RequestParam String friendName) {
        if (StringUtils.isBlank(friendName)) {
            log.error("[解除好友] 好友用户名为空");
            return ResponseEntity.badRequest().body("好友用户名为空");
        }
        String username = SecurityUtils.getCurrentUserLogin();
        io.swagger.client.ApiResponse<?> result = userApi.removeFriend(username, friendName);
        if (result.getStatusCode() == 404) {
            log.error("[解除好友] 此IM用户或被解除的好友不存在");
            return new ResponseEntity<Object>("此IM用户或被解除的好友不存在", HttpStatus.NOT_FOUND);
        }
        return ResponseEntity.ok().body(result.getData());
    }

    @ApiOperation(value = "获取IM用户的好友列表", notes = "获取当前登录账号下的好友列表;前提条件是一定要登录")
    @ApiResponses({
        @ApiResponse(code = 404, message = "此IM用户或要查看的好友不存在"),
        @ApiResponse(code = 200, message = "成功获取到用户好友列表")
    })
    @GetMapping("/users/friends")
    public ResponseEntity<?> getFriends() {
        // 获取当前登录的用户账号
        String username = SecurityUtils.getCurrentUserLogin();

        io.swagger.client.ApiResponse<?> result = userApi.getFriendList(username);
        if (result.getStatusCode() == 404) {
            log.error("此IM用户或要查看的好友不存在;用户:{}", username);
            return new ResponseEntity<Object>("此IM用户或要查看的好友不存在", HttpStatus.NOT_FOUND);
        }
        return new ResponseEntity<>((Object) result.getData(), HttpStatus.OK);
    }

    // ------- 黑名单 --------
    @ApiOperation(value = "获取 IM 用户的黑名单", notes = "获取当前登录账号下的黑名单列表;前提条件是一定要登录")
    @ApiResponses({
        @ApiResponse(code = 404, message = "此IM用户或要查看的黑名单不存在"),
        @ApiResponse(code = 200, message = "成功获取到用户黑名单列表")
    })
    @GetMapping("/users/blacks")
    public ResponseEntity<?> getBlackList() {
        String username = SecurityUtils.getCurrentUserLogin();
        io.swagger.client.ApiResponse<?> result = userApi.getBlackList(username);
        if (result.getStatusCode() == 404) {
            log.error("此IM用户或要查看的黑名单不存在;用户:{}", username);
            return new ResponseEntity<Object>("此IM用户或要查看的黑名单不存在", HttpStatus.NOT_FOUND);
        }
        return new ResponseEntity<>((Object) result.getData(), HttpStatus.OK);
    }

    @ApiOperation(value = "往IM用户的黑名单里加人", notes = "往IM用户的黑名单里加人;前提条件是一定要登录")
    @ApiResponses({
        @ApiResponse(code = 404, message = "此IM用户不存在"),
        @ApiResponse(code = 400, message = "被添加到黑名单的IM用户不存在"),
        @ApiResponse(code = 200, message = "成功获取到用户黑名单列表")
    })
    @ApiImplicitParam(name = "userList", value = "要添加到黑名单的用户列表", required = true, dataType = "List<String>")
    @PostMapping("/users/blacks")
    public ResponseEntity<?> addToBlackList(@RequestBody List<String> userList) {
        String login = SecurityUtils.getCurrentUserLogin();
        UserName userNames = new UserName();
        for (String u : userList) {
            userNames.add(u);
        }
        io.swagger.client.ApiResponse<?> result = userApi.addToBlackList(login, new UserNames().usernames(userNames));
        if (result.getStatusCode() == 404) {
            log.error("此IM用户不存在;用户:{}", login);
            return new ResponseEntity<Object>("此IM用户不存在", HttpStatus.NOT_FOUND);
        }
        if (result.getStatusCode() == 400) {
            log.error("被添加到黑名单的IM用户不存在;用户列表:{}", userList);
            return new ResponseEntity<Object>("被添加到黑名单的IM用户不存在", HttpStatus.BAD_REQUEST);
        }
        return ResponseEntity.ok().body(result.getData());
    }

    @ApiOperation(value = "从IM用户的黑名单里减人", notes = "从IM用户的黑名单里减人;前提条件是一定要登录")
    @ApiResponses({
        @ApiResponse(code = 404, message = "此IM用户或被减的用户不存在"),
        @ApiResponse(code = 200, message = "成功获取到用户黑名单列表")
    })
    @ApiImplicitParam(name = "blackName", value = "要从黑名单列表中删除的用户名", paramType = "query", required = true, dataType = "String")
    @DeleteMapping("/users/blacks")
    public ResponseEntity<?> removeFromBlackList(@RequestParam String blackName) {
        String username = SecurityUtils.getCurrentUserLogin();
        io.swagger.client.ApiResponse<?> result = userApi.removeFromBlackList(username, blackName);
        if (result.getStatusCode() == 404) {
            log.error("此IM用户或被减的用户不存在; 被减用户:{}", blackName);
            return new ResponseEntity<Object>("此IM用户或被减的用户不存在", HttpStatus.NOT_FOUND);
        }
        return ResponseEntity.ok().body(result.getData());
    }

    // --------用户在线状态---------
    @ApiOperation(value = "获取 IM 用户的在线状态", notes = "在线为online,不在线为offline，该信息在返回的数据的data字段中")
    @ApiResponses({
        @ApiResponse(code = 404, message = "此IM用户不存在"),
        @ApiResponse(code = 200, message = "成功获取到用户在线状态")
    })
    @GetMapping("/users/status/{username}")
    public ResponseEntity<?> getUserStatus(@PathVariable String username) {
        if (StringUtils.isBlank(username)) {
            log.error("[获取用户状态] 用户名为空");
            return ResponseEntity.badRequest().body("用户名为空");
        }
        io.swagger.client.ApiResponse<?> result = userApi.getUserStatus(username);
        if (result.getStatusCode() == 404) {
            log.error("[获取用户状态] 此IM用户不存在; 用户名:{}", username);
            return new ResponseEntity<Object>("此IM用户不存在", HttpStatus.NOT_FOUND);
        }
        return ResponseEntity.ok().body(result.getData());
    }

    // -------发送消息--------
    @ApiOperation(value = "给IM用户发送文本信息", notes = "给IM用户发送文本信息")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "message", value = "要发送的文本信息", required = true, dataType = "String"),
        @ApiImplicitParam(name = "target", value = "信息接收方的用户名", required = true, dataType = "String", paramType = "path")
    })
    @ApiResponses({
        @ApiResponse(code = 400, message = "消息发送失败"),
        @ApiResponse(code = 200, message = "发送消息成功")
    })
    @PostMapping("/chat/text/{target}")
    public ResponseEntity<?> sendTextMsg(@RequestBody String message, @PathVariable String target) {
        String from = SecurityUtils.getCurrentUserLogin();

        Msg msg = new Msg();
        MsgContent msgContent = new MsgContent().type(MsgContent.TypeEnum.TXT).msg(message);
        UserName userName = new UserName();
        userName.add(target);

        msg.from(from).target(userName).targetType("users").msg(msgContent);
        io.swagger.client.ApiResponse<?> result = sendMsgApi.sendMsg(msg);
        if (result.getStatusCode() == 400) {
            log.error("[发送文本] 消息发送失败；code={}", result.getStatusCode());
            return ResponseEntity.badRequest().body("信息发送失败");
        }
        return ResponseEntity.ok().body(result.getData());
    }

    @ApiOperation(value = "给IM用户发送多媒体信息", notes = "多媒体信息包括:语音，图片，视频等，目前支持语音，图片")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "mediaMsg", value = "要发送的多媒体文件", required = true, dataType = "File", paramType = "form"),
        @ApiImplicitParam(name = "type", value = "要发送的多媒体消息类型:audio,img", required = true, dataType = "String", paramType = "path"),
        @ApiImplicitParam(name = "target", value = "信息接收方的用户名", required = true, dataType = "String", paramType = "path")})
    @ApiResponses({
        @ApiResponse(code = 400, message = "消息发送失败/各种异常"),
        @ApiResponse(code = 200, message = "发送消息成功")})
    @PostMapping("/chat/{type}/{target}")
    public ResponseEntity<?> sendMediaMsg(@ApiParam() @RequestParam("mediaMsg") MultipartFile mediaMsg,
                                          @PathVariable String type,
                                          @PathVariable String target,
                                          HttpSession session) {
        String from = SecurityUtils.getCurrentUserLogin();
        // 取出发送的消息类型
        String tag = "";
        if ("audio".equals(type)) {
            tag = "语音";
        } else if ("img".equals(type)) {
            tag = "图片";
        }

        if (mediaMsg.isEmpty()) {
            log.error("[发送{}] {}文件为空", tag, tag);
            return ResponseEntity.badRequest().body(String.format("%s文件为空", tag));
        }
        // 取出原始文件名
        String filename = mediaMsg.getOriginalFilename();
        filename = UUID.randomUUID() + filename.substring(filename.lastIndexOf("."));
        log.debug("filename={}", filename);
        String path = session.getServletContext().getRealPath("/temp");
        File dir = new File(path);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        File file = new File(path, filename);
        try {
            mediaMsg.transferTo(file);
        } catch (IOException e) {
            log.error("[发送{}] 转换{}文件发生错误;", tag, tag, e);
            return ResponseEntity.badRequest().body(String.format("转换%s文件发生错误", tag));
        }

        io.swagger.client.ApiResponse<?> uploadResult = fileApi.upload(file);
        // 删除临时文件
        file.delete();
        if (uploadResult.getStatusCode() != 200) {
            log.error("[发送{}] 上传{}文件至环信发送错误", tag, tag);
            return ResponseEntity.badRequest().body(String.format("上传%s文件至环信发送错误", tag));
        }

        JSONObject json = JSON.parseObject((String) uploadResult.getData());

        String url = json.getString("uri");
        JSONArray entities = json.getJSONArray("entities");
        JSONObject entity = null;
        if (entities.size() > 0) {
            entity = entities.getJSONObject(0);
        }
        if (entity == null) {
            log.error("[发送{}] 获取{}文件响应实体为空", tag);
            return ResponseEntity.badRequest().body(String.format("获取%s文件响应实体为空", tag));
        }
        String uuid = entity.getString("uuid");
        url = url + "/" + uuid;
        log.debug("[发送{}] url={}", tag, url);
        String shareSecret = entity.getString("share-secret");
        Msg msg = new Msg();
        UserName targetUser = new UserName();
        targetUser.add(target);

        if ("audio".equals(type)) {
            AudioMsgContent audioMsgContent = new AudioMsgContent();
            audioMsgContent.url(url)
                .secret(shareSecret)
                .filename(filename)
                .type(MsgContent.TypeEnum.AUDIO)
                .msg("this is a audio msg");
            msg.from(from).target(targetUser).targetType("users").msg(audioMsgContent);
        } else if ("img".equals(type)) {
            ImageMsgContent imgMsgContent = new ImageMsgContent();
            imgMsgContent.url(url)
                .secret(shareSecret)
                .filename(filename)
                .type(MsgContent.TypeEnum.IMG)
                .msg("this is a img msg");
            msg.from(from).target(targetUser).targetType("users").msg(imgMsgContent);
        }

        io.swagger.client.ApiResponse<?> result = sendMsgApi.sendMsg(msg);
        if (result.getStatusCode() == 400) {
            log.error("[发送{}] 消息发送失败；code={}", tag, result.getStatusCode());
            return ResponseEntity.badRequest().body(String.format("%s信息发送失败", tag));
        }
        return ResponseEntity.ok().body(result.getData());
    }

    // -------消息记录-------
}
